package com.matt.service.impl;

import com.dotflat.util.AssertUtil;
import com.matt.commons.dto.sso.StaffDTO;
import com.matt.commons.exception.BusinessException;
import com.matt.domain.*;
import com.matt.domain.mp.ParentUser;
import com.matt.domain.rel.RelClassesChildren;
import com.matt.foundation.constant.ChildrenConstant;
import com.matt.foundation.constant.RoleCodeConstant;
import com.matt.foundation.model.ErrorCode;
import com.matt.foundation.utils.DateUtil;
import com.matt.repository.*;
import com.matt.repository.record.ChildrenNurseryInfoRecordRepository;
import com.matt.repository.rel.RelClassesChildrenRepository;
import com.matt.repository.rel.RelClassesTeacherRepository;
import com.matt.service.ChildrenService;
import com.matt.service.LeaveRecordService;
import com.matt.service.WxPushService;
import com.matt.service.remoteCall.SsoCallService;
import org.apache.commons.lang.StringUtils;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.matt.foundation.model.ErrorCode.CHECK_STATUS_ERROR;

@Service
public class LeaveRecordServiceImpl implements LeaveRecordService {

    @Autowired
    LeaveRecordRepository leaveRecordRepository;

    @Autowired
    AppUserRepository appUserRepository;

    @Autowired
    ChildrenRepository childrenRepository;

    @Autowired
    ClassesRepository classesRepository;

    @Autowired
    private RelClassesTeacherRepository relClassesTeacherRepository;

    @Autowired
    RelClassesChildrenRepository relClassesChildrenRepository;

    @Autowired
    private ChildrenExtendInfoRepository childrenExtendInfoRepository;

    @Autowired
    private ChildrenNurseryInfoRecordRepository childrenNurseryInfoRecordRepository;

//    @Autowired
//    RedPointService redPointService ;

    @Autowired
    private WorkDateRepository workDateRepository;

    @Autowired
    SsoCallService ssoCallService;

    @Autowired
    private WxPushService wxPushService;

    @Autowired
    private ChildrenService childrenService;

    private LeaveRecord generateRecord(String leaveDate, String areaId, String source, Integer leaveType, String content){
        Date now = new Date();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
        String today = df.format(now);

        if(today.compareTo(leaveDate) >0)
            throw new BusinessException(ErrorCode.NOT_ROLE_ERROR, "该日期不能请假");

        LeaveRecord leaveRecord = new LeaveRecord();
        leaveRecord.setAreaId(areaId);
        leaveRecord.setSource(source);
        leaveRecord.setLeaveDate(DateUtil.parseToDate(leaveDate));
        leaveRecord.setLeaveType(leaveType);
        leaveRecord.setContent(content);
        leaveRecord.setIscheck(false);

        return leaveRecord;
    }

    @Override
    @Transactional
    public LeaveRecord addParentsRecord(String parentPhone, String childrenId,String leaveDate, Integer leaveType, String content) {

        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(leaveDate);
        Date begin = map.get("beg");
        Date end = map.get("end");

        ParentUser users = appUserRepository.findByPhone(parentPhone);
        if(null == users)
            throw new BusinessException(ErrorCode.STAFF_NOT_EXIST, "家长不存在");
        String usersName = users.getName();
        String userId = users.getId();

        Children children = childrenRepository.getOne(childrenId);
        if(null == children)
            throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "宝宝不存在");
        String childrenName = children.getName();
        String areaId = children.getAreaId();


        LeaveRecord isExist = leaveRecordRepository.findFirstByChildrenIdAndLeaveDateBetweenAndLeaveTypeAndDeletedAndStatusNot(childrenId, begin, end, 3,false, 2);
        if(null != isExist) {
            throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "全天请假记录已存在");
        }else if(leaveType == 3){
            isExist = leaveRecordRepository.findFirstByChildrenIdAndLeaveDateBetweenAndDeletedAndStatusNot(childrenId, begin, end, false, 2);
        }else{
            isExist = leaveRecordRepository.findFirstByChildrenIdAndLeaveDateBetweenAndLeaveTypeAndDeletedAndStatusNot(childrenId, begin, end, leaveType,false, 2);
        }
        if(null != isExist) {
            throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "请假记录已存在");
        }

        LeaveRecord leaveRecord = generateRecord(leaveDate, areaId, "parents", leaveType, content);
        leaveRecord.setChildrenId(childrenId);
        leaveRecord.setChildrenName(childrenName);
        leaveRecord.setUsersName(usersName);
        leaveRecord.setUsersId(userId);

        leaveRecordRepository.save(leaveRecord);
        String roleCode = RoleCodeConstant.ROLE_CODE_TEACHER;

        List<Classes> classes = classesRepository.findAllByChildrenId(childrenId);

        //仅推送到班主任
//        for (Classes c : classes){
//            String teacherId = c.getInChargeTeacherId();
//            redPointService.addRedNumByRoleCodeAndStaffId(areaId, teacherId, roleCode, RedPointConstant.RED_POINT_LEAVE,1);
//        }
        //请假天数
        int  day = DateUtil.birthdayDay(end,begin) + 1;
        ChildrenExtendInfo extendInfo = childrenExtendInfoRepository.findByChildrenId(childrenId);
        WorkDate workDate = workDateRepository.getWorkDateAscDay(extendInfo.getNurseryEndDate(),day);

        if (Objects.nonNull(extendInfo)){
                //可延长天数必须大于0
                if (day > 0 ){
                    //添加考勤流水记录
                    ChildrenNurseryInfoRecord childrenNurseryInfoRecord = new ChildrenNurseryInfoRecord();

                    childrenNurseryInfoRecord.setChildrenId(children.getId());
                    childrenNurseryInfoRecord.setCreatedName(children.getName());
                    childrenNurseryInfoRecord.setStatus(ChildrenConstant.CheckStatus.LEAVE.codeOf());
                    childrenNurseryInfoRecord.setHealthyStatus(0);
                    childrenNurseryInfoRecord.setBeginDate(begin);
                    childrenNurseryInfoRecord.setEndDate(end);
                    childrenNurseryInfoRecord.setEffectDay(day);
                    childrenNurseryInfoRecord.setType(ChildrenConstant.SurplusType.EXTENDED_RECORDS.codeOf());
                    childrenNurseryInfoRecord.setNurseryOriginalEndDate(extendInfo.getNurseryEndDate());
                    if (AssertUtil.isNotEmpty(workDate)){
                        childrenNurseryInfoRecord.setNurseryEndDate(workDate.getWorkDate());
                    }else {
                        childrenNurseryInfoRecord.setNurseryEndDate(DateUtil.addDay(extendInfo.getNurseryEndDate(),day));
                    }
                    childrenNurseryInfoRecord.setRemark("请假："+users.getName()+"家长请假");


                    StaffDTO staffDTO = new StaffDTO();
                    staffDTO.setAreaId(children.getAreaId());
                    staffDTO.setId(users.getId());
                    staffDTO.setRealName(users.getName()+"家长");
                    //修改合同请假天数
                    List<ChildrenContractInfoRecord> contractInfoRecordList = childrenService.getChildrenContractInfoRecord( staffDTO, childrenId, begin, day, 1);

                    if (contractInfoRecordList.size() > 0) {
                        childrenNurseryInfoRecordRepository.save(childrenNurseryInfoRecord);
                        //修改宝宝合同日期
                        extendInfo.setNurseryEndDate(childrenNurseryInfoRecord.getNurseryEndDate());
                        //修改剩余请假天数
                        extendInfo.setSurplusLeaveDay(extendInfo.getSurplusLeaveDay() - day);
                        childrenExtendInfoRepository.save(extendInfo);

                    } else {
                        throw new BusinessException(CHECK_STATUS_ERROR, "合同未生效！");
                    }
                }
        }

        return leaveRecord;
    }

    @Override
    public LeaveRecord addTeacherRecord(String areaId,String teacherId, String teacherName,String leaveDate, Integer leaveType, String content) {
        Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(leaveDate);
        Date begin = map.get("beg");
        Date end = map.get("end");

        LeaveRecord isExist = leaveRecordRepository.findFirstByTeacherIdAndLeaveDateBetweenAndLeaveTypeAndDeletedAndStatusNot(teacherId, begin, end, 3,false, 2);//当天是否有请假记录
        if(null != isExist) {
            throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "全天请假记录已存在");
        }else if(leaveType == 3){
            isExist = leaveRecordRepository.findFirstByTeacherIdAndLeaveDateBetweenAndDeletedAndStatusNot(teacherId, begin, end,false, 2);//当天是否有请假记录
        }else{
            isExist = leaveRecordRepository.findFirstByTeacherIdAndLeaveDateBetweenAndLeaveTypeAndDeletedAndStatusNot(teacherId, begin, end, leaveType,false, 2);//当天是否有请假记录
        }
        if(null != isExist) {
            throw new BusinessException(ErrorCode.CHILDREN_NOT_EXIST, "请假记录已存在");
        }

        LeaveRecord leaveRecord = generateRecord(leaveDate, areaId, "teacher", leaveType, content );

        leaveRecord.setTeacherName(teacherName);
        leaveRecord.setTeacherId(teacherId);
        leaveRecordRepository.save(leaveRecord);

        String roleCode = RoleCodeConstant.ROLE_CODE_LEADER;

//        List<String> staffIdList = ssoCallService.getLeaderStaffIdByArea(areaId);
//        for(String staffId:staffIdList){
//            redPointService.addRedNumByRoleCodeAndStaffId(areaId,staffId,roleCode, RedPointConstant.RED_POINT_LEAVE,1);
//        }

        return leaveRecord;
    }

    @Override
    public Page<LeaveRecord> getWxLeaveRecord(String childrenId, String month, Integer pageNum, Integer pageSize) {

        Date dateBegin = null;
        Date dateEnd = null;
        if (StringUtils.isNotEmpty(month)) {
            if (month.indexOf("/") > 0){
                dateBegin = DateUtil.parseToDate(month + "/01");
            }else{
                dateBegin = DateUtil.parseToDate(month + "-01");
            }

            Calendar cal = Calendar.getInstance();//获取一个Calendar对象
            cal.setTime(dateBegin);
            cal.add(Calendar.MONTH, 1);//获取当前时间的下一个月

            dateEnd = cal.getTime();
        }

        Date finalDateEnd = dateEnd;
        Date finalDateBegin = dateBegin;
        Specification<LeaveRecord> specification = new Specification<LeaveRecord>() {
            @Override
            public Predicate toPredicate(Root<LeaveRecord> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<>();
                if (StringUtils.isNotBlank(childrenId))
                    predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("childrenId"), childrenId)));
                predicates.add(criteriaBuilder.and(criteriaBuilder.equal(root.get("deleted"), false)));
                if (finalDateBegin != null && finalDateEnd != null) {
                    predicates.add(criteriaBuilder.between(root.get("leaveDate"), finalDateBegin, finalDateEnd));
                }
                query.where(predicates.toArray(new Predicate[predicates.size()]));
                query.orderBy(criteriaBuilder.desc(root.get("leaveDate")));
                return query.getRestriction();
            }
        };

        Page<LeaveRecord> page = leaveRecordRepository.findAll(specification, PageRequest.of(pageNum, pageSize));
        List<LeaveRecord> list = Lists.newArrayList();
        page.getContent().stream().forEach(o -> {
            list.add(o);
        });

        return new PageImpl(list, PageRequest.of(pageNum, pageSize), page.getTotalElements());
    }

    @Override
    public Page<LeaveRecord> getAppLeaveRecord(String areaId,String staffId,String source, Integer pageNum, Integer pageSize) {

     /*   Map<String, Date> map = DateUtil.getCurrentDayBeginAndEnd(leaveDate);
        Date begin = map.get("beg");
        Date end = map.get("end");*/


        if("parents".equals(source)) {
            //TODO: sql查询缩减
            //老师查询家长请假申请
            List<Classes> classes = classesRepository.findByInChargeTeacherIdAndAreaIdAndDeleted(staffId, areaId, false);
            List<String> classIdList = classes.stream().map(k->k.getId()).collect(Collectors.toList());

            List<RelClassesChildren> relClassesChildrenList =   relClassesChildrenRepository.findAllByClassesIdIn(classIdList);

            List<String> childrenIdList = relClassesChildrenList.stream().map(k->k.getChildrenId()).collect(Collectors.toList());

            if(childrenIdList.size() == 0){
                throw new BusinessException(ErrorCode.ID_IS_ERROR, "该老师没有主管班级，或班级没有关联宝宝");
            }


            Pageable pageable = PageRequest.of(pageNum, pageSize);
            Page<LeaveRecord> page = leaveRecordRepository.findAllByAreaIdAndSourceAndChildrenIdInAndDeletedOrderByCreatedDesc(areaId, source, childrenIdList, false, pageable);

            return page;
        }

        if("teacher".equals(source)) {
            //园长查询老师请假
            Pageable pageable = PageRequest.of(pageNum, pageSize);
            Page<LeaveRecord> page = leaveRecordRepository.findAllByAreaIdAndSourceAndDeletedOrderByCreatedDesc(areaId, source, false, pageable);
            return page;
        }

        if("self".equals(source)) {
            //老师查询自己的请假记录
            Pageable pageable = PageRequest.of(pageNum, pageSize);
            Page<LeaveRecord> page = leaveRecordRepository.findAllByAreaIdAndTeacherIdAndDeletedOrderByCreatedDesc(areaId, staffId, false, pageable);

            return page;
        }

        if("doctor".equals(source)) {
            //儿保查询家长请假申请

            Pageable pageable = PageRequest.of(pageNum, pageSize);
            Page<LeaveRecord> page = leaveRecordRepository.findAllByAreaIdAndSourceAndDeletedOrderByCreatedDesc(areaId, "parents", false, pageable);
            return page;
        }
        return null;

    }

    @Override
    public void checkLeaveRecord(String staffId, String staffName, String leaveRecordId, String comment) {
       LeaveRecord leaveRecord = leaveRecordRepository.getOne(leaveRecordId);
        if(null == leaveRecord)
            throw new BusinessException(ErrorCode.ID_IS_ERROR, "请假记录ID不存在");
        leaveRecord.setCheckStaffId(staffId);
        leaveRecord.setCheckStaffName(staffName);
        leaveRecord.setIscheck(true);
        leaveRecord.setStatus(1);
        leaveRecord.setStatusVal("同意");
        leaveRecord.setCheckComment(comment);

        if(leaveRecord.getSource().equals("parents")){
            //家长请假发送推送
            wxPushService.pushLeaveRecord(leaveRecord, null);
        }

        leaveRecordRepository.save(leaveRecord);
    }

    @Override
    public void refuseLeaveRecord(String staffId, String staffName, String leaveRecordId, String comment){
        LeaveRecord leaveRecord = leaveRecordRepository.getOne(leaveRecordId);
        if(null == leaveRecord)
            throw new BusinessException(ErrorCode.ID_IS_ERROR, "请假记录ID不存在");
        leaveRecord.setCheckStaffId(staffId);
        leaveRecord.setCheckStaffName(staffName);
        leaveRecord.setIscheck(true);
        leaveRecord.setStatus(2);
        leaveRecord.setStatusVal("拒绝");
        leaveRecord.setCheckComment(comment);

        if(leaveRecord.getSource().equals("parents")){
            //家长请假发送推送
            wxPushService.pushLeaveRecord(leaveRecord, null);
        }

        leaveRecordRepository.save(leaveRecord);
    }

    @Override
    public void deleteLeaveRecord(String staffId, String staffName, String leaveRecordId) {
        LeaveRecord leaveRecord = leaveRecordRepository.getOne(leaveRecordId);
        if(null == leaveRecord)
            throw new BusinessException(ErrorCode.ID_IS_ERROR, "请假记录ID不存在");
        String teacherId = leaveRecord.getTeacherId();
        if(!teacherId.equals(staffId))
            throw new BusinessException(ErrorCode.NOT_ROLE_ERROR, "无权操作");

        Date now = new Date();
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");//设置日期格式
        String today = df.format(now);
        String leaveDate = df.format(leaveRecord.getLeaveDate());

        if(today.compareTo(leaveDate) >0)
            throw new BusinessException(ErrorCode.NOT_ROLE_ERROR, "该日期不能删除");

        leaveRecord.setDeleted(true);
        leaveRecordRepository.save(leaveRecord);


    }

    @Override
    public List<LeaveRecord> getMyLeaveRecordByDate(String staffId, String beginDate, String endDate) {

        Map<String, Date> beginMap = DateUtil.getCurrentDayBeginAndEnd(beginDate);
        Date begin = beginMap.get("beg");

        Map<String, Date> endMap = DateUtil.getCurrentDayBeginAndEnd(endDate);
        Date end = endMap.get("end");

        return leaveRecordRepository.findAllByTeacherIdAndLeaveDateBetweenAndDeletedOrderByCreatedDesc(staffId, begin, end, false);
    }
}
